/**
 * 
 */
package com.oron3.bouncer.objects.shapes;


/**
 * Point in 3 dim space in the carthesian format
 * 
 * @author Ofek
 *
 */
public class Point implements Cloneable, Shape {
	public static final Point ZERO = new Point(0, 0, 0);
	public float x;
	public float y;
	public float z;

	public Point(final float x, final float y, final float z) {
		this.x = x;
		this.y = y;
		this.z = z;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#clone()
	 */
	@Override
	public Point clone() {
		try {
			return (Point) super.clone();
		}
		catch (final CloneNotSupportedException e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 
	 */
	public Point() {}

	public void set(final Point p) {
		x = p.x;
		y = p.y;
		z = p.z;
	}

	/**
	 * @param x2
	 * @param y2
	 * @param z2
	 */
	public void set(final float x2, final float y2, final float z2) {
		x = x2;
		y = y2;
		z = z2;
	}

	/**
	 * @param x2
	 * @param y2
	 * @param z2
	 */
	public void move(final float dx, final float dy, final float dz) {
		x += dx;
		y += dy;
		z += dz;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "(" + x + "," + y + "," + z + ")";

	}

	/**
	 * @return
	 */
	public PPoint toPolar() {
		final double r = Math.sqrt(x * x + y * y + z * z);
		return new PPoint((float) r, (float) Math.atan2(y, x), (float) Math.acos(z / r));
	}

	/**
	 * @param cache
	 */
	public void toPolar(final PPoint cache) {
		cache.r = (float) Math.sqrt(x * x + y * y + z * z);
		cache.a = (float) Math.atan2(y, x);
		cache.b = (float) Math.acos(z / cache.r);

	}

	/**
	 * @param p1
	 * @return
	 */
	public Point sub(final Point p) {
		return new Point(x - p.x, y - p.y, z - p.z);
	}

	/**
	 * @param mul
	 * @return
	 */
	public Point add(final Point p) {
		return new Point(x + p.x, y + p.y, z + p.z);
	}

	/**
	 * @return
	 */
	public boolean isZero() {
		return x == y && y == z && x == 0;
	}

	/**
	 * @param i
	 * @return
	 */
	public Point mul(final float factor) {
		return new Point(x * factor, y * factor, z * factor);
	}

	/**
	 * @param b
	 * @return
	 */
	public float distance(final Point other) {
		final Vector distanceVector = new Vector(other.sub(this));
		return distanceVector.length();
	}

	/**
	 * @return
	 */
	public Vector toVector() {
		return new Vector(x, y, z);
	}

	/**
	 * @param p1
	 * @param p2
	 * @return
	 */
	public static Point min(final Point p1, final Point p2) {
		return null;
	}

	/**
	 * @return
	 */
	public float length() {
		return (float) Math.sqrt(x * x + y * y + z * z);
	}

	/**
	 * @param i
	 * @param j
	 * @param lz
	 * @return
	 */
	public Point add(final float x, final float y, final float z) {
		return new Point(x + this.x, y + this.y, z + this.z);
	}

	/**
	 * @param i
	 * @param j
	 * @param k
	 * @return
	 */
	public Point sub(final float x, final float y, final float z) {
		return new Point(this.x - x, this.y - y, this.z - z);
	}



	/*
	 * (non-Javadoc)
	 * 
	 * @see com.oron3.bouncer.objects.shapes.Shape#intersects(com.oron3.bouncer.objects.shapes.Shape)
	 */
	@Override
	public boolean intersects(final Shape o) {
		return false;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.oron3.bouncer.objects.shapes.Shape#intersection(com.oron3.bouncer.objects.shapes.Shape)
	 */
	@Override
	public Intersection intersection(final Shape o) {
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.oron3.bouncer.objects.shapes.Shape#calcRelation(com.oron3.bouncer.objects.shapes.Shape)
	 */
	@Override
	public int describeRelation(final Shape o) {
		throw new IllegalArgumentException();
	}

	/* (non-Javadoc)
	 * @see com.oron3.bouncer.objects.shapes.Shape#isInside(com.oron3.bouncer.objects.shapes.Shape)
	 */
	@Override
	public boolean isInside(final Shape o) {
		throw new IllegalArgumentException();
	}

	/* (non-Javadoc)
	 * @see com.oron3.bouncer.objects.shapes.Shape#project(com.oron3.bouncer.objects.shapes.Shape)
	 */
	@Override
	public Shape project(final Shape o) {
		throw new IllegalArgumentException();
	}
	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(final Object o) {
		if (super.equals(o)) return true;
		if (!(o instanceof Point )) return false; 
		final Point p = (Point) o;
		return p.x==x&&p.y==y&&p.z==z;
	}

	/* (non-Javadoc)
	 * @see com.oron3.bouncer.objects.shapes.Shape#collision(com.oron3.bouncer.objects.shapes.Shape, com.oron3.bouncer.objects.shapes.Vector)
	 */
	@Override
	public Collision collision(final Shape shape, final Vector v) {
		return null;
	}
}